home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 1 Issue 2 / PDCD-1 - Issue 02.iso / _utilities / utilities / 001 / fue / c / basic next >
Text File  |  1991-06-24  |  19KB  |  622 lines

  1. /*
  2.  * The routines in this file move the cursor around on the screen. They
  3.  * compute a new value for the cursor, then adjust ".". The display code
  4.  * always updates the cursor location, so only moves between lines, or
  5.  * functions that adjust the top line in the window and invalidate the
  6.  * framing, are hard.
  7.  */
  8.  
  9. /*      Modifications:
  10.         03-Oct-89       Mike Burrow (INMOS)     Added folding.
  11. */
  12.  
  13. #include        <stdio.h>
  14. #include        "estruct.h"
  15. #include        "etype.h"
  16. #include        "edef.h"
  17. #include        "elang.h"
  18.  
  19. /*
  20.  * Move the cursor to the
  21.  * beginning of the current line.
  22.  * Trivial.
  23.  */
  24. PASCAL NEAR gotobol(f, n)
  25. {
  26.         curwp->w_doto  = 0;
  27.         return(TRUE);
  28. }
  29.  
  30. /*
  31.  * Move the cursor backwards by "n" characters. If "n" is less than zero call
  32.  * "forwchar" to actually do the move. Otherwise compute the new cursor
  33.  * location. Error if you try and move out of the buffer. Set the flag if the
  34.  * line pointer for dot changes.
  35.  */
  36.  
  37. /*{{{  PASCAL NEAR backchar(f, n)*/
  38. PASCAL NEAR backchar(f, n)
  39. register int    n;
  40. {
  41.         register LINE   *lp;
  42.  
  43.         if (n < 0)
  44.                 return(forwchar(f, -n));
  45.         while (n--) {
  46.                 if (curwp->w_doto == 0) {
  47.                         if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
  48.                                 return(FALSE);
  49.                         curwp->w_dotp  = lp;
  50.                         curwp->w_doto  = llength(lp);
  51.                         curwp->w_flag |= WFMOVE;
  52.                 } else
  53.                         curwp->w_doto--;
  54.         }
  55.         return(TRUE);
  56. }
  57. /*}}}*/
  58.  
  59. /*
  60.  * Move the cursor to the end of the current line. Trivial. No errors.
  61.  */
  62.  
  63. /*{{{  PASCAL NEAR gotoeol(f, n)*/
  64. PASCAL NEAR gotoeol(f, n)
  65. {
  66.         curwp->w_doto  = llength(curwp->w_dotp);
  67.         return(TRUE);
  68. }
  69. /*}}}*/
  70.  
  71. /*
  72.  * Move the cursor forwards by "n" characters. If "n" is less than zero call
  73.  * "backchar" to actually do the move. Otherwise compute the new cursor
  74.  * location, and move ".". Error if you try and move off the end of the
  75.  * buffer. Set the flag if the line pointer for dot changes.
  76.  */
  77.  
  78. /*{{{  PASCAL NEAR forwchar(f, n)*/
  79. PASCAL NEAR forwchar(f, n)
  80. register int    n;
  81. {
  82.         if (n < 0)
  83.                 return(backchar(f, -n));
  84.         while (n--) {
  85.                 if (curwp->w_doto == llength(curwp->w_dotp)) {
  86.                         if (curwp->w_dotp == curbp->b_linep)
  87.                                 return(FALSE);
  88.                         curwp->w_dotp  = lforw(curwp->w_dotp);
  89.                         curwp->w_doto  = 0;
  90.                         curwp->w_flag |= WFMOVE;
  91.                 } else
  92.                         curwp->w_doto++;
  93.         }
  94.         return(TRUE);
  95. }
  96. /*}}}*/
  97.  
  98. /* move to a particular line.
  99.  
  100. /*{{{  PASCAL NEAR gotoline(f, n)*/
  101. PASCAL NEAR gotoline(f, n)
  102.  
  103.  /*                        argument (n) must be a positive integer for
  104.                            this to actually do anything         */
  105.  
  106. {
  107.         register int status;    /* status return */
  108.         char arg[NSTRING];      /* buffer to hold argument */
  109.  
  110.         /* get an argument if one doesnt exist */
  111.         if (f == FALSE) {
  112.                 if ((status = mlreply(TEXT7, arg, NSTRING)) != TRUE) {
  113. /*                                    "Line to GOTO: " */
  114.                         mlwrite(TEXT8);
  115. /*                              "[Aborted]" */
  116.                         return(status);
  117.                 }
  118.                 n = asc_int(arg);
  119.         }
  120.  
  121.         if (n < 1)              /* if a bogus argument...then leave */
  122.                 return(FALSE);
  123.  
  124.         /* first, we go to the start of the buffer */
  125.         curwp->w_dotp  = lforw(curbp->b_linep);
  126.         curwp->w_doto  = 0;
  127.         return(forwline(f, n-1, TRUE));
  128. }
  129. /*}}}*/
  130.  
  131. /*
  132.  * Goto the beginning of the buffer. Massive adjustment of dot. This is
  133.  * considered to be hard motion; it really isn't if the original value of dot
  134.  * is the same as the new value of dot. Normally bound to "M-<".
  135.  */
  136.  
  137. /*{{{  PASCAL NEAR gotobob(f, n)*/
  138. PASCAL NEAR gotobob(f, n)
  139. {
  140.         curwp->w_dotp  = lforw(curbp->b_linep);
  141.         curwp->w_doto  = 0;
  142.         curwp->w_flag |= WFHARD;
  143.         return(TRUE);
  144. }
  145. /*}}}*/
  146.  
  147. /*
  148.  * Move to the end of the buffer. Dot is always put at the end of the file
  149.  * (ZJ). The standard screen code does most of the hard parts of update.
  150.  * Bound to "M->".
  151.  */
  152.  
  153. /*{{{  PASCAL NEAR gotoeob(f, n)*/
  154. PASCAL NEAR gotoeob(f, n)
  155. {
  156.         curwp->w_dotp  = curbp->b_linep;
  157.         curwp->w_doto  = 0;
  158.         curwp->w_flag |= WFHARD;
  159.         return(TRUE);
  160. }
  161. /*}}}*/
  162.  
  163.  
  164. /*
  165.  * Move forward by full lines bound to "C-N". 
  166.  * Just calls forwline, with raw = FALSE.
  167.  * Required because bound keys have form fun(f, n).
  168.  */
  169.  
  170. /*{{{  PASCAL NEAR bforwline(f, n)*/
  171. PASCAL NEAR bforwline(f, n)
  172. {
  173.         return(forwline(f, n, FALSE));
  174. }
  175. /*}}}*/
  176.  
  177.  
  178. /*
  179.  * Move forward by full lines. If the number of lines to move is less than
  180.  * zero, call the backward line function to actually do it. The last command
  181.  * controls how the goal column is set. Bound to "C-N". No errors are
  182.  * possible.
  183.  * If raw is TRUE then enter folds, else skip them. MJB: 13-Oct-89 
  184.  */
  185.  
  186. /*{{{  PASCAL NEAR forwline(f, n, raw)*/
  187. PASCAL NEAR forwline(f, n, raw)
  188. {
  189.         register LINE   *dlp;
  190.  
  191.         if (n < 0)
  192.                 return(backline(f, -n, raw));
  193.  
  194.         /* if we are on the last line as we start....fail the command */
  195.         if (curwp->w_dotp == curbp->b_linep)
  196.                 return(FALSE);
  197.  
  198.         /* if the last command was not note a line move,
  199.            reset the goal column */
  200.         if ((lastflag&CFCPCN) == 0)
  201.                 curgoal = getccol(FALSE);
  202.  
  203.         /* flag this command as a line move */
  204.         thisflag |= CFCPCN;
  205.  
  206.         /* and move the point down */
  207.         dlp = curwp->w_dotp;
  208.         while (n-- && dlp!=curbp->b_linep)
  209.                 if (raw) /* raw mode */
  210.                         dlp = dlp->l_fp;
  211.                 else   /* it's cooked */
  212.                         dlp = lforw(dlp);
  213.  
  214.         /* reseting the current position */
  215.         curwp->w_dotp  = dlp;
  216.         curwp->w_doto  = getgoal(dlp);
  217.         curwp->w_flag |= WFMOVE;
  218.  
  219.         if (raw) /* may have entered closed folds */
  220.                 openoutfolds();
  221.  
  222.         return(TRUE);
  223. }
  224. /*}}}*/
  225.  
  226.  
  227. /*
  228.  * This function is like "bforwline", but goes backwards.
  229.  * Bound to "C-P". Required because bound functions have form fun(f, n).
  230.  */
  231.  
  232. /*{{{  PASCAL NEAR bbackline(f, n)*/
  233. PASCAL NEAR bbackline(f, n)
  234. {
  235.         return(backline(f, n, FALSE));
  236. }
  237. /*}}}*/
  238.  
  239.  
  240. /*
  241.  * This function is like "forwline", but goes backwards. The scheme is exactly
  242.  * the same. Check for arguments that are less than zero and call your
  243.  * alternate. Figure out the new line and call "movedot" to perform the
  244.  * motion. No errors are possible. Bound to "C-P".
  245.  * If raw is TRUE then enter folds, else skip them. MJB: 13-Oct-89
  246.  */
  247.  
  248. /*{{{  PASCAL NEAR backline(f, n, raw)*/
  249. PASCAL NEAR backline(f, n, raw)
  250. {
  251.         register LINE   *dlp;
  252.  
  253.         if (n < 0)
  254.                 return(forwline(f, -n, raw));
  255.  
  256.  
  257.         /* if we are on the last line as we start....fail the command */
  258.         if (lback(curwp->w_dotp) == curbp->b_linep)
  259.                 return(FALSE);
  260.  
  261.         /* if the last command was not note a line move,
  262.            reset the goal column */
  263.         if ((lastflag&CFCPCN) == 0)
  264.                 curgoal = getccol(FALSE);
  265.  
  266.         /* flag this command as a line move */
  267.         thisflag |= CFCPCN;
  268.  
  269.         /* and move the point up */
  270.         dlp = curwp->w_dotp;
  271.         while (n-- && lback(dlp)!=curbp->b_linep)
  272.                 if (raw) /* raw mode */
  273.                         dlp = dlp->l_bp;
  274.                 else   /* it's cooked */
  275.                         dlp = lback(dlp);
  276.  
  277.         /* reseting the current position */
  278.         curwp->w_dotp  = dlp;
  279.         curwp->w_doto  = getgoal(dlp);
  280.         curwp->w_flag |= WFMOVE;
  281.  
  282.         if (raw) /* may have entered folds */
  283.                 openoutfolds();
  284.  
  285.         return(TRUE);
  286. }
  287. /*}}}*/
  288.  
  289. #if     WORDPRO
  290.  
  291.  /* go back to the beginning of the current paragraph
  292.     here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  293.     OR A START OF FOLD (MJB: 03-Oct-89),
  294.     combination to delimit the beginning of a paragraph  */
  295.  
  296. /*{{{  PASCAL NEAR gotobop(f, n)*/
  297. PASCAL NEAR gotobop(f, n)
  298.  
  299. int f, n;       /* default Flag & Numeric argument */
  300.  
  301. {
  302.         register int suc;       /* success of last backchar */
  303.  
  304.         if (n < 0)      /* the other way...*/
  305.                 return(gotoeop(f, -n));
  306.  
  307.         while (n-- > 0) {       /* for each one asked for */
  308.  
  309.                 /* first scan back until we are in a word or foldline */
  310.                 suc = backchar(FALSE, 1);
  311.                 while (!inword() && suc && 
  312.                        ((curwp->w_dotp->l_type == LNORMAL) ||
  313.                         (curwp->w_dotp->l_type == LEOEFOLD)))
  314.                         suc = backchar(FALSE, 1);
  315.                 curwp->w_doto = 0;      /* and go to the B-O-Line */
  316.  
  317.                 /* and scan back until we hit a <NL><NL> or <NL><TAB>
  318.                    or a <NL><SPACE> or foldline */
  319.                 if (curwp->w_dotp->l_type == LNORMAL)
  320.                         while (lback(curwp->w_dotp) != curbp->b_linep)
  321.                         {       if (llength(curwp->w_dotp) != 0 &&
  322.                                     curwp->w_dotp->l_type == LNORMAL &&
  323.                                     lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
  324.                                     lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
  325.                                         curwp->w_dotp = lback(curwp->w_dotp);
  326.                                 else
  327.                                         break;
  328.                         }
  329.                 /* and then forward until we are in a word */
  330.                 if (curwp->w_dotp->l_type == LNORMAL) {
  331.                         suc = forwchar(FALSE, 1);
  332.                         while (suc && !inword())
  333.                                 suc = forwchar(FALSE, 1);
  334.                 }
  335.                 else { /* find the fold symbol */
  336.                         suc = lgetc(curwp->w_dotp, curwp->w_doto);
  337.                         while (suc && ((suc == ' ') || (suc == TAB)))
  338.                                 suc = forwchar(FALSE, 1);
  339.                 }
  340.         }
  341.         curwp->w_flag |= WFMOVE;        /* force screen update */
  342.         return(TRUE);
  343. }
  344. /*}}}*/
  345.  
  346.  /* go forword to the end of the current paragraph
  347.     here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  348.     OR A FOLDLINE (MJB: 03-Oct-89),
  349.     combination to delimit the beginning of a paragraph  */
  350.  
  351. /*{{{  PASCAL NEAR gotoeop(f, n)*/
  352. PASCAL NEAR gotoeop(f, n)
  353. int f, n;       /* default Flag & Numeric argument */
  354.  
  355. {
  356.         register int suc;       /* success of last backchar */
  357.         LINE *startp;
  358.  
  359.         if (n < 0)      /* the other way...*/
  360.                 return(gotobop(f, -n));
  361.  
  362.         while (n-- > 0) {       /* for each one asked for */
  363.  
  364.                 /* first scan forward until we are in a word or foldline */
  365.                 suc = forwchar(FALSE, 1);
  366.                 startp = curwp->w_dotp;
  367.                 while (!inword() && suc && 
  368.                        ((curwp->w_dotp->l_type == LNORMAL) ||
  369.                         (curwp->w_dotp->l_type == LSOEFOLD)))
  370.                         suc = forwchar(FALSE, 1);
  371.                 curwp->w_doto = 0;      /* and go to the B-O-Line */
  372.                 if (suc && ((curwp->w_dotp->l_type == LNORMAL) ||
  373.                             (curwp->w_dotp->l_type == LSOEFOLD))) /* of next line if not at EOF or fold */
  374.                         curwp->w_dotp = lforw(curwp->w_dotp);
  375.  
  376.                 /* and scan forword until we hit a <NL><NL> or <NL><TAB>
  377.                    or a <NL><SPACE>or a foldline */
  378.                 while (curwp->w_dotp != curbp->b_linep) {
  379.                         if (llength(curwp->w_dotp) != 0 &&
  380.                             curwp->w_dotp->l_type == LNORMAL &&
  381.                             lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
  382.                             lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
  383.                                 curwp->w_dotp = lforw(curwp->w_dotp);
  384.                         else
  385.                                 break;
  386.                 }
  387.  
  388.                 /* and then backward until we are in a word */
  389.                 /* don't do anything if fold line, just goto the EOL */
  390.                 if (curwp->w_dotp->l_type == LNORMAL) {
  391.                         suc = backchar(FALSE, 1);
  392.                         while (suc && !inword())
  393.                                 suc = backchar(FALSE, 1);
  394.                 }
  395.  
  396.                 /* goto end of line, unless LSOFOLD beyond start point */
  397.                 if ((curwp->w_dotp->l_type == LSOFOLD) &&
  398.                     (curwp->w_dotp != startp))
  399.                         curwp->w_doto = 0;
  400.                 else
  401.                         curwp->w_doto = llength(curwp->w_dotp); /* and to the EOL */
  402.         }
  403.         curwp->w_flag |= WFMOVE;        /* force screen update */
  404.         return(TRUE);
  405. }
  406. /*}}}*/
  407.  
  408. #endif
  409.  
  410. /*
  411.  * This routine, given a pointer to a LINE, and the current cursor goal
  412.  * column, return the best choice for the offset. The offset is returned.
  413.  * Used by "C-N" and "C-P".
  414.  */
  415.  
  416. /*{{{  PASCAL NEAR getgoal(dlp)*/
  417. PASCAL NEAR getgoal(dlp)
  418. register LINE   *dlp;
  419. {
  420.         register int    c;
  421.         register int    col;
  422.         register int    newcol;
  423.         register int    dbo;
  424.  
  425.         col = 0;
  426.         dbo = 0;
  427.         while (dbo != llength(dlp)) {
  428.                 c = lgetc(dlp, dbo);
  429.                 newcol = col;
  430.                 if (c == '\t')
  431.                         newcol += -(newcol % tabsize) + (tabsize - 1);
  432.                 else if (c<0x20 || c==0x7F)
  433.                         ++newcol;
  434.                 ++newcol;
  435.                 if (newcol > curgoal)
  436.                         break;
  437.                 col = newcol;
  438.                 ++dbo;
  439.         }
  440.         return(dbo);
  441. }
  442. /*}}}*/
  443.  
  444. /*
  445.  * Scroll forward by a specified number of lines, or by a full page if no
  446.  * argument. Bound to "C-V". The "2" in the arithmetic on the window size is
  447.  * the overlap; this value is the default overlap value in ITS EMACS. Because
  448.  * this zaps the top line in the display window, we have to do a hard update.
  449.  */
  450.  
  451. /*{{{  PASCAL NEAR forwpage(f, n)*/
  452. PASCAL NEAR forwpage(f, n)
  453. register int    n;
  454. {
  455.         register LINE   *lp;
  456.  
  457.         if (f == FALSE) {
  458.                 n = curwp->w_ntrows - 2;        /* Default scroll.      */
  459.                 if (n <= 0)                     /* Forget the overlap   */
  460.                         n = 1;                  /* if tiny window.      */
  461.         } else if (n < 0)
  462.                 return(backpage(f, -n));
  463. #if     CVMVAS
  464.         else                                    /* Convert from pages   */
  465.                 n *= curwp->w_ntrows;           /* to lines.            */
  466. #endif
  467.         lp = curwp->w_linep;
  468.         while (n-- && lp!=curbp->b_linep)
  469.                 lp = lforw(lp);
  470.         curwp->w_linep = lp;
  471.         curwp->w_dotp  = lp;
  472.         curwp->w_doto  = 0;
  473.         curwp->w_flag |= WFHARD;
  474.         return(TRUE);
  475. }
  476. /*}}}*/
  477.  
  478. /*
  479.  * This command is like "forwpage", but it goes backwards. The "2", like
  480.  * above, is the overlap between the two windows. The value is from the ITS
  481.  * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
  482.  * reason.
  483.  */
  484.  
  485. /*{{{  PASCAL NEAR backpage(f, n)*/
  486. PASCAL NEAR backpage(f, n)
  487.  
  488. register int f;
  489. register int n;
  490.  
  491. {
  492.         register LINE   *lp;
  493.  
  494.         if (f == FALSE) {
  495.                 n = curwp->w_ntrows - 2;        /* Default scroll.      */
  496.                 if (n <= 0)                     /* Don't blow up if the */
  497.                         n = 1;                  /* window is tiny.      */
  498.         } else if (n < 0)
  499.                 return(forwpage(f, -n));
  500. #if     CVMVAS
  501.         else                                    /* Convert from pages   */
  502.                 n *= curwp->w_ntrows;           /* to lines.            */
  503. #endif
  504.         lp = curwp->w_linep;
  505.         while (n-- && lback(lp)!=curbp->b_linep)
  506.                 lp = lback(lp);
  507.         curwp->w_linep = lp;
  508.         curwp->w_dotp  = lp;
  509.         curwp->w_doto  = 0;
  510.         curwp->w_flag |= WFHARD;
  511.         return(TRUE);
  512. }
  513. /*}}}*/
  514.  
  515. /*
  516.  * Set the mark in the current window to the value of "." in the window. No
  517.  * errors are possible. Bound to "M-.".
  518.  */
  519.  
  520. /*{{{  PASCAL NEAR setmark(f, n) */
  521. PASCAL NEAR setmark(f, n) 
  522. {
  523.         /* make sure it is in range */
  524.         if (f == FALSE)
  525.                 n = 0;
  526.         n %= NMARKS;
  527.  
  528.         curwp->w_markp[n] = curwp->w_dotp;
  529.         curwp->w_marko[n] = curwp->w_doto;
  530.         mlwrite(TEXT9, n);
  531. /*              "[Mark %d set]" */
  532.         return(TRUE);
  533. }
  534. /*}}}*/
  535.  
  536. /*
  537.  * Remove the mark in the current window.
  538.  * Bound to ^X <space> 
  539.  */
  540.  
  541. /*{{{  PASCAL NEAR remmark(f, n)*/
  542. PASCAL NEAR remmark(f, n)
  543. {
  544.         /* make sure it is in range */
  545.         if (f == FALSE)
  546.                 n = 0;
  547.         n %= NMARKS;
  548.  
  549.         curwp->w_markp[n] = NULL;
  550.         curwp->w_marko[n] = 0;
  551.         mlwrite(TEXT10, n);
  552. /*              "[Mark %d removed]" */
  553.         return(TRUE);
  554. }
  555. /*}}}*/
  556.  
  557. /*
  558.  * Swap the values of "." and "mark" in the current window. This is pretty
  559.  * easy, bacause all of the hard work gets done by the standard routine
  560.  * that moves the mark about. The only possible error is "no mark". Bound to
  561.  * "C-X C-X".
  562.  */
  563.  
  564. /*{{{  PASCAL NEAR swapmark(f, n)*/
  565. PASCAL NEAR swapmark(f, n)
  566. {
  567.         register LINE   *odotp;
  568.         register int    odoto;
  569.  
  570.         /* make sure it is in range */
  571.         if (f == FALSE)
  572.                 n = 0;
  573.         n %= NMARKS;
  574.  
  575.         if (curwp->w_markp[n] == NULL) {
  576.                 mlwrite(TEXT11, n);
  577. /*                      "No mark %d in this window" */
  578.                 return(FALSE);
  579.         }
  580.         odotp = curwp->w_dotp;
  581.         odoto = curwp->w_doto;
  582.         curwp->w_dotp  = curwp->w_markp[n];
  583.         curwp->w_doto  = curwp->w_marko[n];
  584.         curwp->w_markp[n] = odotp;
  585.         curwp->w_marko[n] = odoto;
  586.         curwp->w_flag |= WFMOVE;
  587.         openoutfolds();
  588.         return(TRUE);
  589. }
  590. /*}}}*/
  591.  
  592. /*
  593.  * Goto a mark in the current window. This is pretty easy, bacause all of
  594.  * the hard work gets done by the standard routine that moves the mark
  595.  * about. The only possible error is "no mark". Bound to "M-^G".
  596.  */
  597.  
  598. /*{{{  PASCAL NEAR gotomark(f, n)*/
  599. PASCAL NEAR gotomark(f, n)
  600.  
  601. int f, n;       /* default and nemeric args */
  602.  
  603. {
  604.         /* make sure it is in range */
  605.         if (f == FALSE)
  606.                 n = 0;
  607.         n %= NMARKS;
  608.  
  609.         if (curwp->w_markp[n] == NULL) {
  610.                 mlwrite(TEXT11, n);
  611. /*                      "No mark %d in this window" */
  612.                 return(FALSE);
  613.         }
  614.         curwp->w_dotp  = curwp->w_markp[n];
  615.         curwp->w_doto  = curwp->w_marko[n];
  616.         curwp->w_flag |= WFMOVE;
  617.         openoutfolds();
  618.         return(TRUE);
  619. }
  620. /*}}}*/
  621.  
  622.